package ca.uwo.android.campusmap;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import ca.uwo.android.R;

import android.app.SearchManager;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.provider.BaseColumns;

public class BuildingDatabase {
	private final BuildingSuggestionHelper helper;

	public static final String BUILDING_NAME = SearchManager.SUGGEST_COLUMN_TEXT_1;
	public static final String LONGITUDE = "_longitude";
	public static final String LATITUDE = "_latitude";
	public static final String ADDRESS = "_address";

	private static final String DATABASE_NAME = "buildings.db";
	private static final String TABLE_NAME = "building";

	// Build table with building names
	private static final String CREATE_TABLE = "CREATE VIRTUAL TABLE " + TABLE_NAME +
			" USING fts3 (" + 
				BUILDING_NAME + "," + 
				LONGITUDE + "," +
				LATITUDE + "," +
				ADDRESS + ");";

	private static final HashMap<String,String> mBuildingMap = buildBuildingMap();

	public BuildingDatabase(Context context) {
		helper = new BuildingSuggestionHelper(context);
	}

	// Build Column Map
	private static HashMap<String, String> buildBuildingMap() {
		HashMap<String,String> map = new HashMap<String,String>();
		map.put(BUILDING_NAME, BUILDING_NAME);
		map.put(LONGITUDE, LONGITUDE);
		map.put(LATITUDE, LATITUDE);
		map.put(ADDRESS, ADDRESS);
		map.put(BaseColumns._ID, "rowid AS " + BaseColumns._ID);
		map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " +
				SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
		
		return map;
	}

	public Cursor getBuilding(String rowId, String[] columns) {
		String selection = "rowid = ?";
		String[] selectionArgs = new String[] {rowId};

		return query(selection, selectionArgs, columns);
	}

	public Cursor getWordMatches(String query, String[] columns) {
		String selection = null;
		String[] selectionArgs = null;
		if(query.length() > 0) {
			selection = BUILDING_NAME + " MATCH ?";
			selectionArgs = new String[] {query+"*"};
		}
		
		Cursor result = query(selection, selectionArgs, columns);
		return result;
	}

	private Cursor query(String selection, String[] selectionArgs, String[] columns) {
		SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
		builder.setTables(TABLE_NAME);
		builder.setProjectionMap(mBuildingMap);
		Cursor cursor = builder.query(helper.getReadableDatabase(),	columns, selection, selectionArgs, null, null, null);

		if (cursor == null) {
			return null;
		} 
		else if (!cursor.moveToFirst()) {
			cursor.close();
			return null;
		}
		return cursor;
	}

	private class BuildingSuggestionHelper extends SQLiteOpenHelper {

		private SQLiteDatabase mDatabase;
		private BuildingList buildings;
		
		private static final int DATABASE_VERSION = 1;

		BuildingSuggestionHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
			buildings = buildList(context);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			mDatabase = db;
			mDatabase.execSQL(CREATE_TABLE);
			loadData(buildings);
		}

		protected void loadData(BuildingList buildings) {
			for(int i = 0; i < buildings.getSize(); i++) {
				addBuilding(buildings.getBuildingData(i));
			}
		}

		public long addBuilding(BuildingData data) {
			ContentValues value = new ContentValues();
			value.put(BUILDING_NAME, data.getBuilding());
			value.put(LONGITUDE, data.getLongitude());
			value.put(LATITUDE, data.getLatitude());
			value.put(ADDRESS, data.getAddress());

			return mDatabase.insert(TABLE_NAME, null, value);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			throw new UnsupportedOperationException();
		}				
		
		protected BuildingList buildList(Context context) {
			// XML handling
			try {
				InputStream is =  context.getResources().openRawResource(R.raw.buildings);
				SAXParserFactory factory = SAXParserFactory.newInstance();
				SAXParser parser = factory.newSAXParser();
				XMLReader reader = parser.getXMLReader();
				SaxBuildingHandler handler = new SaxBuildingHandler();

				reader.setContentHandler(handler);
				reader.parse(new InputSource(is));

				return handler.getBuildingList();

			}
			catch(SAXException e) {
				e.printStackTrace();
				return null;
			} 
			catch (ParserConfigurationException e) {
				e.printStackTrace();
				return null;
			} 
			catch (IOException e) {
				e.printStackTrace();
				return null;
			}
		}
	}
}
